<html>
<head><meta charset="utf-8"><title>Lifetime cast · project-safe-transmute · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/index.html">project-safe-transmute</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/Lifetime.20cast.html">Lifetime cast</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="217350009"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/Lifetime%20cast/near/217350009" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/Lifetime.20cast.html#217350009">(Nov 20 2020 at 00:43)</a>:</h4>
<p>Regarding "more safe transmute", I think it would be nice to have a transmute operation that changes only lifetimes. This is obviously unsafe, and if we make it too easy to access it might be a problem for those getting over the lifetime and borrowing phase of rust learning, but it could protect against accidentally casting other kinds of things at the same time. E.g. <code>lifetime_cast::&lt;&amp;'a mut T, &amp;'b mut T&gt;(t)</code> is okay but <code>lifetime_cast::&lt;&amp;'a mut T, &amp;'b mut u8&gt;(t)</code> is not. I think this might be part of the most general version of the safe-transmute RFC involving the <code>Neglect*</code> tags but not any of the versions that are limited to only safe transmutes.</p>



<a name="217350069"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/Lifetime%20cast/near/217350069" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/Lifetime.20cast.html#217350069">(Nov 20 2020 at 00:44)</a>:</h4>
<p>Is it ever valid to extend lifetimes? Or are you in raw pointer territory then?</p>



<a name="217350091"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/Lifetime%20cast/near/217350091" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/Lifetime.20cast.html#217350091">(Nov 20 2020 at 00:45)</a>:</h4>
<p>It might be that rust's borrow checker has underestimated the lifetime</p>



<a name="217350156"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/Lifetime%20cast/near/217350156" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/Lifetime.20cast.html#217350156">(Nov 20 2020 at 00:46)</a>:</h4>
<p>Sure, I recognize why you might want to do it. Are you allowed to?</p>



<a name="217350169"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/Lifetime%20cast/near/217350169" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/Lifetime.20cast.html#217350169">(Nov 20 2020 at 00:46)</a>:</h4>
<p><a href="https://stackoverflow.com/questions/64902078/is-this-safe-logically-splitting-a-borrow">This recent SO question of mine</a> has an example, and generally speaking any example for Polonius or other more advanced lifetime analyses should apply here</p>



<a name="217350184"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/Lifetime%20cast/near/217350184" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/Lifetime.20cast.html#217350184">(Nov 20 2020 at 00:47)</a>:</h4>
<p>Gotcha.</p>



<a name="217350187"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/Lifetime%20cast/near/217350187" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/Lifetime.20cast.html#217350187">(Nov 20 2020 at 00:47)</a>:</h4>
<p>true lifetime inference is undecidable, so such examples will always exist</p>



<a name="217350195"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/Lifetime%20cast/near/217350195" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/Lifetime.20cast.html#217350195">(Nov 20 2020 at 00:47)</a>:</h4>
<p>Sounds like there ought to be a <code>NeglectLifetime</code> option!</p>



<a name="217350198"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/Lifetime%20cast/near/217350198" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/Lifetime.20cast.html#217350198">(Nov 20 2020 at 00:47)</a>:</h4>
<p>so <code>lifetime_cast</code> will always be either a no-op or necessarily <code>unsafe</code></p>



<a name="217364650"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/Lifetime%20cast/near/217364650" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Quy Nguyen <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/Lifetime.20cast.html#217364650">(Nov 20 2020 at 05:40)</a>:</h4>
<p>That seems like a massive footgun to me :/ We can document all we want that unsafe does not turn of the borrow checker, but having a lifetime_cast means that it's a lot easier to just get code to compile.</p>
<p>Is there a source for lifetime inference being undecidable, not withstanding things self-referential structs? Seems like the thing Polonius or something after that can solve.</p>



<a name="217365779"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/Lifetime%20cast/near/217365779" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/Lifetime.20cast.html#217365779">(Nov 20 2020 at 06:08)</a>:</h4>
<p>Besides Rice's theorem you mean? (which can be paraphrased "every interesting property of programs is undecidable")</p>



<a name="217366192"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/Lifetime%20cast/near/217366192" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/Lifetime.20cast.html#217366192">(Nov 20 2020 at 06:18)</a>:</h4>
<p>A simple example:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">struct</span> <span class="nc">NonCopyStruct</span><span class="p">(</span><span class="kt">u8</span><span class="p">);</span><span class="w"></span>
<span class="kd">let</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">NonCopyStruct</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span><span class="w"></span>
<span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">0</span><span class="o">..</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">  </span><span class="k">if</span><span class="w"> </span><span class="n">interesting_property</span><span class="p">(</span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nb">drop</span><span class="p">(</span><span class="n">x</span><span class="p">);</span><span class="w"> </span><span class="n">println</span><span class="o">!</span><span class="p">(</span><span class="s">"{}"</span><span class="p">,</span><span class="w"> </span><span class="n">x</span><span class="p">.</span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>Assuming the borrow checker is disabled, this code causes UB if and only if some <code>i</code> satisfying <code>interesting_property(i)</code> is true. We can insert your favorite undecidable predicate in there (for example, turing machine M halts in i steps). No borrow checker implementation can accept this code, but for some choices of <code>interesting_property</code> the code will nevertheless be sound.</p>



<a name="217366255"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/Lifetime%20cast/near/217366255" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/Lifetime.20cast.html#217366255">(Nov 20 2020 at 06:20)</a>:</h4>
<p>It's not that lifetime inference is undecidable, in the sense that you can make some rules that describe some conservative over-approximation of the dynamic "true lifetimes" that is decidable, but rather that any such decidable scheme is necessarily a proper over-approximation.</p>



<a name="217366343"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/Lifetime%20cast/near/217366343" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/Lifetime.20cast.html#217366343">(Nov 20 2020 at 06:23)</a>:</h4>
<p>The original borrow checker algorithm was such an approximation, NLL is a better approximation, and polonius is better still; but they are all just approximations of an undecidable predicate. The undecidable predicate itself is important because it is how we judge soundness of the borrow checkers; NLL would just be unsound if measured on the original borrow checker's rules, because it allows programs that would not satisfy those rules.</p>



<a name="217430365"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/Lifetime%20cast/near/217430365" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Henry-Mantilla <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/Lifetime.20cast.html#217430365">(Nov 20 2020 at 17:08)</a>:</h4>
<p>The way I do it is like this:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="cp">#[allow(nonstandard_style)]</span><span class="w"></span>
<span class="k">pub</span><span class="w"></span>
<span class="k">struct</span> <span class="nc">lifetimes</span><span class="o">&lt;'</span><span class="na">src</span><span class="p">,</span><span class="w"> </span><span class="o">'</span><span class="na">dst</span><span class="o">&gt;</span><span class="p">(</span><span class="o">*</span><span class="k">mut</span><span class="w"> </span><span class="o">&amp;'</span><span class="na">src</span><span class="w"> </span><span class="p">(),</span><span class="w"> </span><span class="o">*</span><span class="k">mut</span><span class="w"> </span><span class="o">&amp;'</span><span class="na">dst</span><span class="w"> </span><span class="p">());</span><span class="w"></span>

<span class="k">impl</span><span class="o">&lt;'</span><span class="na">src</span><span class="p">,</span><span class="w"> </span><span class="o">'</span><span class="na">dst</span><span class="o">&gt;</span><span class="w"> </span><span class="n">lifetimes</span><span class="o">&lt;'</span><span class="na">src</span><span class="p">,</span><span class="w"> </span><span class="o">'</span><span class="na">dst</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="sd">/// A.k.a. "trans_mut"</span>
<span class="w">    </span><span class="k">pub</span><span class="w"></span>
<span class="w">    </span><span class="k">unsafe</span><span class="w"> </span><span class="k">fn</span> <span class="nf">cast_mut</span><span class="o">&lt;</span><span class="n">Referee</span><span class="w"> </span>: <span class="o">?</span><span class="nb">Sized</span><span class="o">&gt;</span><span class="w"> </span><span class="p">(</span><span class="w"></span>
<span class="w">        </span><span class="n">reference</span>: <span class="kp">&amp;</span><span class="o">'</span><span class="na">src</span> <span class="nc">mut</span><span class="w"> </span><span class="n">Referee</span><span class="p">,</span><span class="w"></span>
<span class="w">    </span><span class="p">)</span><span class="w"> </span>-&gt; <span class="kp">&amp;</span><span class="o">'</span><span class="na">dst</span> <span class="nc">mut</span><span class="w"> </span><span class="n">Referee</span><span class="w"></span>
<span class="w">    </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span>::<span class="n">core</span>::<span class="n">mem</span>::<span class="n">transmute</span><span class="p">(</span><span class="n">reference</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="k">pub</span><span class="w"></span>
<span class="w">    </span><span class="k">unsafe</span><span class="w"> </span><span class="k">fn</span> <span class="nf">cast_ref</span><span class="o">&lt;</span><span class="n">Referee</span><span class="w"> </span>: <span class="o">?</span><span class="nb">Sized</span><span class="o">&gt;</span><span class="w"> </span><span class="p">(</span><span class="w"></span>
<span class="w">        </span><span class="n">reference</span>: <span class="kp">&amp;</span><span class="o">'</span><span class="na">src</span> <span class="nc">Referee</span><span class="w"></span>
<span class="w">    </span><span class="p">)</span><span class="w"> </span>-&gt; <span class="kp">&amp;</span><span class="o">'</span><span class="na">dst</span> <span class="nc">Referee</span><span class="w"></span>
<span class="w">    </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span>::<span class="n">core</span>::<span class="n">mem</span>::<span class="n">transmute</span><span class="p">(</span><span class="n">reference</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>Which allows writing, for instance,</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">unsafe</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">lifetimes</span>::<span class="o">&lt;'</span><span class="nb">_</span><span class="p">,</span><span class="w"> </span><span class="o">'</span><span class="nb">static</span><span class="o">&gt;</span>::<span class="n">cast_mut</span><span class="p">(</span><span class="n">a_mut_ref</span><span class="p">)</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>(the type-as-a-generic-module-hack is needed to be able to early-bind lifetimes, <em>i.e.</em>, to actually specify lifetime parameters).</p>



<a name="217459827"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/Lifetime%20cast/near/217459827" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/Lifetime.20cast.html#217459827">(Nov 20 2020 at 21:16)</a>:</h4>
<p>This is limited to changing <code>&amp;'a T</code> to <code>&amp;'b T</code> though (which is admittedly most of the use cases of this). I was envisioning it to also include <code>&amp;'a T&lt;'c&gt;</code> to <code>&amp;'b T&lt;'d&gt;</code> as well. It occurs to me that you can probably make this work with unsafe variance overrides, if you take the input, wrap it in a newtype, make everything covariant and then coerce it to the new lifetimes. (But that's also a feature that doesn't exist to my knowledge.)</p>



<a name="217476502"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/Lifetime%20cast/near/217476502" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Henry-Mantilla <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/Lifetime.20cast.html#217476502">(Nov 21 2020 at 00:50)</a>:</h4>
<p>My bad, I missed the fact your were looking for the ability to transmute an arbitrary number of lifetimes. Doing that explicit variance override on a wrapper sounds interesting (more generally, variance overrides would be neat)</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>